/**
 * 计算给定数字的平方根
 * @param {number} x - 输入的数字
 * @returns {Array} - 返回一个数组，包含计算得到的平方根和迭代次数
 */
function sqrt(x) {
  // 当输入的数字小于2时，直接返回该数字及其平方作为结果和迭代次数
  if (x < 2) return [x, 1];
  let res = x, // 初始化结果为输入的数字本身
    pre = res, // 初始化前一次结果为输入的数字本身
    count = 0; // 初始化迭代次数为0
  // 使用牛顿迭代法计算平方根
  while (true) {
    // 更新前一次结果为更接近平方根的值
    pre = (pre + x / pre) / 2;
    count++; // 增加迭代次数
    // 当结果与前一次结果的差的绝对值小于指定精度时，结束迭代
    if (Math.abs(res - pre) < 1e-7) break;
    res = pre; // 更新结果为前一次结果
  }
  return [res, count]; // 返回计算得到的平方根和迭代次数
}
function fastInverseSqrt(x) {
  if (typeof x !== "number" || isNaN(x)) {
    throw new Error("Input must be a valid number.");
  }

  if (x <= 0) {
    return x === 0 ? Infinity : NaN;
  }

  // 计算 x 的一半
  let halfX = 0.5 * x;

  // 获取 x 的位表示
  let i = new Uint32Array(new Float32Array([x]).buffer)[0];

  // 应用卡马克的神奇公式
  i = 0x5f3759df - (i >>> 1);

  // 将位表示转换回浮点数
  let y = new Float32Array(new Uint32Array([i]).buffer)[0];

  // 迭代一步以提高精度
  y = y * (1.5 - halfX * y * y);

  return 1 / y;
}
// 测试自定义sqrt函数和Math.sqrt函数的性能和准确性
const num = 91; // 设置待计算的数字

const now2 = performance.now(); // 获取当前时间作为Math.sqrt函数的基准
const res2 = fastInverseSqrt(num); // 使用Math.sqrt函数计算num的平方根
console.log(
  // 输出Math.sqrt函数的结果和性能信息
  "fastInverseSqrt",
  res2,
  `误差：${Math.abs(Math.sqrt(num) - res2)}`,
  `用时： ${performance.now() - now2} ms`
);
const now = performance.now(); // 获取当前时间作为基准
const [res, count] = sqrt(num); // 使用自定义sqrt函数计算num的平方根
console.log(
  "mySqrt",
  res,
  `迭代次数：${count}`,
  `误差：${Math.abs(Math.sqrt(num) - res)}`,
  `用时： ${performance.now() - now} ms`
); // 输出结果和性能信息
